/* Microsoft Reference Implementation for TPM 2.0
 *
 *  The copyright in this software is being made available under the BSD License,
 *  included below. This software may be subject to other third party and
 *  contributor rights, including patent rights, and no such rights are granted
 *  under this license.
 *
 *  Copyright (c) Microsoft Corporation
 *
 *  All rights reserved.
 *
 *  BSD License
 *
 *  Redistribution and use in source and binary forms, with or without modification,
 *  are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this list
 *  of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice, this
 *  list of conditions and the following disclaimer in the documentation and/or
 *  other materials provided with the distribution.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "Tpm.h"
#include "Attest_spt_fp.h"
#include "GetCommandAuditDigest_fp.h"

#if CC_GetCommandAuditDigest  // Conditional expansion of this file

/*(See part 3 specification)
// Get current value of command audit log
*/
//  Return Type: TPM_RC
//      TPM_RC_KEY          key referenced by 'signHandle' is not a signing key
//      TPM_RC_SCHEME       'inScheme' is incompatible with 'signHandle' type; or
//                          both 'scheme' and key's default scheme are empty; or
//                          'scheme' is empty while key's default scheme requires
//                          explicit input scheme (split signing); or
//                          non-empty default key scheme differs from 'scheme'
//      TPM_RC_VALUE        digest generated for the given 'scheme' is greater than
//                          the modulus of 'signHandle' (for an RSA key);
//                          invalid commit status or failed to generate "r" value
//                          (for an ECC key)
/*
Part3,
This command returns the current value of the command audit digest, a digest of the commands being audited, and the audit hash algorithm. 
These values are placed in an attestation structure and signed with the key referenced by signHandle.
NOTE 1 See 18.1 for description of how the signing scheme is selected.
When this command completes successfully, and signHandle is not TPM_RH_NULL, the audit digest is cleared. If signHandle is TPM_RH_NULL, 
signature is the Empty Buffer and the audit digest is not cleared.
NOTE 2 The way that the TPM tracks that the digest is clear is vendor-dependent. 
The reference implementation resets the size of the digest to zero.
If this command is being audited, then the signed digest produced by the command will not include the command. At the end of this command, 
the audit digest will be extended with cpHash and the rpHash of the command, which would change the command audit digest signed by the next 
invocation of this command.
This command requires authorization from the privacy administrator of the TPM (expressed with Endorsement Authorization) as well as 
authorization to use the key associated with signHandle.
此命令返回命令审计摘要的当前值、被审计命令的摘要和审计散列算法。
这些值放置在证明结构中，并使用 signHandle 引用的密钥进行签名。
注 1 关于如何选择签名方案的描述见 18.1。
当此命令成功完成且 signHandle 不是 TPM_RH_NULL 时，审核摘要将被清除。 如果 signHandle 是 TPM_RH_NULL，signature 是空缓冲区，审计摘要不会被清除。
注 2 TPM 跟踪摘要是否清晰的方式取决于供应商。
参考实现将摘要的大小重置为零。
如果正在审核此命令，则该命令生成的签名摘要将不包括该命令。 在此命令结束时，审计摘要将使用命令的 cpHash 和 rpHash 进行扩展，这将更改由下一次调用此命令签名的命令审计摘要。
此命令需要 TPM 隐私管理员的授权（用 Endorsement Authorization 表示）以及使用与 signHandle 关联的密钥的授权。

*/
TPM_RC
TPM2_GetCommandAuditDigest(
    GetCommandAuditDigest_In    *in,            // IN: input parameter list
    GetCommandAuditDigest_Out   *out            // OUT: output parameter list
    )
{
    TPM_RC                  result;
    TPMS_ATTEST             auditInfo;
    OBJECT                 *signObject = HandleToObject(in->signHandle);
// Input validation
    if(!IsSigningObject(signObject))
        return TPM_RCS_KEY + RC_GetCommandAuditDigest_signHandle;
    if(!CryptSelectSignScheme(signObject, &in->inScheme))
        return TPM_RCS_SCHEME + RC_GetCommandAuditDigest_inScheme;

// Command Output
    // Fill in attest information common fields
    FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
                     &auditInfo);

    // CommandAuditDigest specific fields
    auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT;
    auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg;
    auditInfo.attested.commandAudit.auditCounter = gp.auditCounter;

    // Copy command audit log
    auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest;
    CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest);

    // Sign attestation structure.  A NULL signature will be returned if
    // signHandle is TPM_RH_NULL.  A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
    // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
    // this point
    result = SignAttestInfo(signObject, &in->inScheme, &auditInfo,
                            &in->qualifyingData, &out->auditInfo,
                            &out->signature);
    // Internal Data Update
    if(result == TPM_RC_SUCCESS && in->signHandle != TPM_RH_NULL)
        // Reset log
        gr.commandAuditDigest.t.size = 0;

    return result;
}

#endif // CC_GetCommandAuditDigest